from uuid import UUID

from sqlalchemy import desc, or_
from sqlalchemy.orm import Session

import models
import schemas
from models import Role, Status, User, RandomCode
from schemas import OrganizationCreate, RespIn
from utils import get_hashed_password


def get_req(db: Session, req_id: int):
    return db.query(models.Request).filter(models.Request.id == req_id).first()


def get_user_last_req(db: Session, user_id: UUID, offset: int):
    return db.query(models.Request).order_by(desc(models.Request.id)) \
        .filter(models.Request.user_id == user_id).offset(offset).first()


def get_reqs_by_topic(db: Session, topic: str):
    return db.query(models.Request).filter(models.Request.topic.icontains(topic)).first()


def get_user_reqs(db: Session, user_id: UUID, skip: int = 0, limit: int = 10):
    return db.query(models.Request).filter(models.Request.user_id == user_id).offset(skip).limit(limit).all()


def get_all_user_reqs(db: Session, user_id: UUID):
    return db.query(models.Request).filter(models.Request.user_id == user_id).all()


def create_req(db: Session, req: schemas.ReqCreate, creator_id: UUID):
    db_req = models.Request(topic=req.topic, description=req.description, user_id=creator_id)
    db_req.statuses.append(Status.Open.with_time())
    db.add(db_req)
    db.commit()
    db.refresh(db_req)
    return db_req


def create_organization(db: Session, org: OrganizationCreate):
    db_org = models.Organization(name=org.name, inn=org.inn)
    db.add(db_org)
    db.commit()
    db.refresh(db_org)
    return db_org


def get_user(db: Session, user_id: UUID):
    return db.query(models.User).filter(models.User.id == user_id,
                                        models.User.is_verified.is_(True)).first()


def get_users(db: Session):
    return db.query(models.User).filter(models.User.is_verified.is_(True)).all()


def get_user_by_name(db: Session, name: str):
    return db.query(models.User).filter(models.User.name == name,
                                        models.User.is_verified.is_(True)).first()


def create_unconfirmed_user(db: Session, user: schemas.UserRegistration, organization_id: int):
    password = get_hashed_password(user.password)
    db_user = models.User(name=user.name, password=password,
                          organization_id=organization_id,
                          role=Role.User, email=user.email,
                          is_verified=False)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user


def confirm_user(db: Session, user: models.User):
    user.is_verified = True
    db.add(user)
    db.commit()
    db.refresh(user)
    return user


def get_user_by_email(db: Session, email: str):
    return db.query(models.User).filter(models.User.is_verified.is_(True),
                                        or_(models.User.email == email)).first()


def get_user_by_name_or_email(db: Session, login: str):
    return db.query(models.User).filter(models.User.is_verified.is_(True),
                                        or_(models.User.name == login, models.User.email == login)).first()


def change_user_password(db: Session, user: User, new_password: str):
    user.password = get_hashed_password(new_password)
    db.add(user)
    db.commit()


def get_organization_by_name(db: Session, name: str):
    return db.query(models.Organization).filter(models.Organization.name.icontains(name)).first()


def get_organization_by_name_or_inn(db: Session, value: str):
    return db.query(models.Organization).filter(or_(models.Organization.name == value,
                                                    models.Organization.inn == value)).first()


def get_organization(db: Session, organization_id: int):
    return db.query(models.Organization).filter(models.Organization.id == organization_id).first()


def create_resp(db: Session, req_id: int, resp_in: RespIn, user_id: UUID):
    db_resp = models.Response(description=resp_in.description, user_id=user_id,
                              request_id=req_id)
    req = get_req(db, req_id)
    cur_stat = req.current_status
    cur_stat.is_current = False
    req.statuses.append(Status.InProgress.with_time())
    db.add(db_resp)
    db.add(req)
    db.commit()
    db.refresh(db_resp)
    return db_resp


def get_resp_by_req_id(db: Session, req_id: int):
    return db.query(models.Response).filter(models.Response.request_id == req_id).first()


def get_unconfirmed_user(db: Session, user_id: UUID):
    return db.query(models.User).filter(models.User.is_verified.is_(False),
                                        models.User.id == user_id).first()


def create_random_code(db: Session, user: User):
    db_code = RandomCode()
    user.code = db_code
    db.add(user)
    db.commit()
    db.refresh(db_code)
    return db_code


def get_code(db: Session, id: UUID):
    return db.query(models.RandomCode).filter(models.RandomCode.id == id).first()